#include<iostream>

#include<vector>
#include<unordered_map>
#include<cstdint>
#include<cassert>
#include<cstring>
#include<string>
#include<ctime>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include <fcntl.h> 
#include <sys/stat.h>
#include <sys/types.h>
#include<functional>
#include<sys/epoll.h>
#define INFO 0 
#define DEBUG 1
#define ERROR 2
#define DEFAULT_LEVEL 1
#define LOG(leval,format,...) do{\
    if(leval < DEFAULT_LEVEL) break;\
    time_t t = time(NULL);\
    struct tm* ltm = localtime(&t);\
    char tmp[32] = {0};\
    strftime(tmp,31,"%H:%M:%S",ltm);\
    fprintf(stdout,"[%s:%s:%d]" format "\n",tmp,__FILE__,__LINE__,##__VA_ARGS__);\
    }while(0)
#define INFO_LOG(format,...) LOG(INFO,format,##__VA_ARGS__)
#define DEBUG_LOG(format,...) LOG(DEBUG,format,##__VA_ARGS__)
#define ERROR_LOG(format,...) LOG(ERROR,format,##__VA_ARGS__)
const static int BUFFER_DEFAULT_SIZE = 1024;
#define MAX_LISTEN_SIZE 1024
//Buffer模块
class Buffer
{
public:
    Buffer()
    :_buffer(BUFFER_DEFAULT_SIZE),
    _reader_idx(0),
    _writer_idx(0)
    {

    }
    ~Buffer(){}
    //缓冲区初始位置
    char* Begin(){return &*_buffer.begin();}
    //获取当前写位置
    char* WritePosition()
    {
        return Begin()+_writer_idx;
    }
    //获取当前读位置
    char* ReadPosition()
    {
        return Begin()+_reader_idx;
    }
    //获取缓冲区末尾空闲大小--写位置之后
    uint64_t TailIdlSize(){return _buffer.size() - _writer_idx;}
    //获取缓冲区开头空闲大小--读位置之前
    uint64_t HeadIdlSize(){return _reader_idx;}
    //获取可读空间大小
    uint64_t ReadAbleSize(){return _writer_idx - _reader_idx;}
    //读指针向后偏移
    void MoveReadOffset(uint64_t len)
    {
        if(len == 0) return;
        assert(len <= ReadAbleSize());
        _reader_idx += len;
    }
    //写指针向后偏移
    void MoveWriteOffset(uint64_t len)
    {
        if(len == 0) return;
        assert(len <= TailIdlSize());
        _writer_idx += len;
    }
    //确保可写空间足够（移动/扩容）
    void EnsureWriteAble(uint64_t len)
    {
        //可以直接在末尾写
        if(len <= TailIdlSize()) return;
        //前后空间足够--移动
        if(len <= TailIdlSize()+HeadIdlSize())
        {
            uint64_t rsz = ReadAbleSize();//记录当前可读大小
            std::copy(ReadPosition(),ReadPosition()+rsz,Begin());
            //移动读写指针
            _reader_idx = 0;
            _writer_idx = rsz;
        }
        //不够--扩容
        else{
            uint64_t rsz = ReadAbleSize();//记录当前可读大小
            _buffer.resize(_writer_idx + rsz);
              //移动读写指针
            _reader_idx = 0;
            _writer_idx = rsz;
        }
    }
    //写入数据
    void Write(const void* data,uint64_t len)
    {
        assert(len > 0);
        EnsureWriteAble(len);
        char* d = (char*)data;
        std::copy(d,d+len,WritePosition());
    }
    //写入数据并移动
    void WriteAndPush(void* data,uint64_t len)
    {
        Write(data,len);
        MoveWriteOffset(len);
    }
    //写入一个字符串
    void WriteString(const std::string& str)
    {
        Write(str.c_str(),str.size());
    }
    void WriteStringAndPush(const std::string& str)
    {
        WriteString(str);
        MoveWriteOffset(str.size());
    }
    //写入另一个Buffer
    void WriteBuffer(Buffer& buffer)
    {
        Write(buffer.ReadPosition(),buffer.ReadAbleSize());
    }
    void WriteBufferAndPush(Buffer& buffer)
    {
        Write(buffer.ReadPosition(),buffer.ReadAbleSize());
        MoveWriteOffset(buffer.ReadAbleSize());
    }
    //读取数据
    void Read(void* buffer,uint64_t len)
    {
        assert(len > 0);
        assert(len <= ReadAbleSize());
        std::copy(ReadPosition(),ReadPosition()+len,(char*)buffer);
    }
    void ReadAndPop(void* buffer,uint64_t len)
    {
        Read(buffer,len);
        MoveReadOffset(len);
    }
    //读取到的数据当作string返回
    std::string ReadAsString(uint64_t len)
    {
        assert(len > 0 && len <= ReadAbleSize());
        std::string ret;
        ret.resize(len);
        Read(&ret[0],len);
        return ret;
    }
    std::string ReadAsStringAndPop(uint64_t len)
    {
        assert(len > 0 && len <= ReadAbleSize());
        std::string ret = ReadAsString(len);
        MoveReadOffset(len);
        return ret;
    }

    //寻找换行
    char* FindCRLF()
    {
        char* ret = (char*)memchr(ReadPosition(),'\n',ReadAbleSize());
        return ret;
    }
    //获取一行
    // std::string GetLine()
    // {
    //     char* ret = FindCRLF();
    //     if(ret == NULL) return "";
    //     uint64_t len = ret - ReadPosition();
    //     std::string str;
    //     str.resize(len);
    //     std::copy(ReadPosition(),ret+1,&str[0]);
    //     return str;
    // }
    std::string GetLine()
    {
        char* ret = FindCRLF();
        if(ret == NULL) return "";
        //把\n也取出来
        return ReadAsString(ret - ReadPosition() + 1);
    }
    std::string GetLineAndPop()
    {
        char* ret = FindCRLF();
        if(ret == NULL) return "";
        std::string str = ReadAsString(ret - ReadPosition() + 1); 
        MoveReadOffset(str.size());
        return str;
    } 
    //清空缓冲区
    void Clear()
    {
        _reader_idx = _writer_idx = 0;
    }
        
private:
    std::vector<char> _buffer;
    uint64_t _reader_idx;
    uint64_t _writer_idx;

};

//Socket模块
class Socket
{
public:
    Socket(){_sockfd = -1;}
    Socket(int sockfd){_sockfd = sockfd;}
    ~Socket(){Close();}
    //创建
    bool Create()
    {
        _sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if(_sockfd < 0)
        {
            ERROR_LOG("Creat socket failed!");
            return false;
        }
        return true;
    }
    //绑定
    bool Bind(const std::string& ip,uint16_t port)
    {
        struct sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = inet_addr(ip.c_str());
        addr.sin_port = htons(port);
        if(bind(_sockfd,(struct sockaddr*)&addr,sizeof(addr)) < 0)
        {
            ERROR_LOG("Bind socket failed!");
            return false;
        }
        return true;
    }
    //监听
    bool Listen(int backlog = MAX_LISTEN_SIZE)
    {
        if(listen(_sockfd,backlog) < 0)
        {
            ERROR_LOG("Listen socket failed!");
            return false;
        }
        return true;
    }
    //主动连接
    bool Connect(const std::string& ip,uint16_t port)
    {
        struct sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = inet_addr(ip.c_str());
        addr.sin_port = htons(port);
        if(connect(_sockfd,(struct sockaddr*)&addr,sizeof(addr)) < 0)
        {
            ERROR_LOG("Connect socket failed!");
            return false;
        }
        return true;
    }
    //接收连接
    int Accept()
    {
        int sockfd = accept(_sockfd, NULL, NULL);
        if (sockfd < 0)
        {
            if (errno == EAGAIN || errno == EWOULDBLOCK)
            {
                // 没有新连接，不是错误
                return -1;
            }
            ERROR_LOG("Accept socket failed!");
            return -1;
        }
        return sockfd;
    }
    //发送数据
    ssize_t Send(const void* buffer,uint64_t len,int flag = 0)
    {
        ssize_t ret = send(_sockfd,buffer,len,flag);
        if(ret < 0)
        {
            //满了或者被中断 <0
            if(errno == EAGAIN || errno == EINTR)
            {
                return 0;
            }
            ERROR_LOG("Send socket failed!");
            return -1;
        }
        return ret;
    }
    //发送数据(非阻塞)
    ssize_t SendNoBlock(const void* buffer,uint64_t len)
    {
        return Send(buffer,len,MSG_DONTWAIT);
    }
    //接收数据
    ssize_t Recv(void* buffer,uint64_t len,int flag = 0)
    {
        ssize_t ret = recv(_sockfd,buffer,len,flag);
        if(ret < 0)
        {
            //被中断 ==0
            if(errno == EAGAIN || errno == EINTR)
            {
                return 0;
            }
            ERROR_LOG("Recv socket failed!");
            return -1;
        }
        return ret;
    }
    ssize_t RecvNoBlock(void* buffer,uint64_t len)
    {
        return Recv(buffer,len,MSG_DONTWAIT);
    }

    //关闭
    void Close()
    {
        close(_sockfd);
    }
    //创建服务器连接
    bool CreatServer(uint16_t port,const std::string& ip = "0.0.0.0",bool flag = false)
    {
        if(!Create()) return false;
        if(flag) SetNonBlock();
        if(!Bind(ip,port)) return false;
        if(!Listen()) return false;
        ReuseAddress();
        return true;
    }
    //创建客户端连接
    bool CreatClient(uint16_t port,const std::string& ip)
    {
        if(!Create()) return false;
        if(!Connect(ip,port)) return false;
        return true;
    }


    //恢复端口可用性,服务器高性能的体现
    //SO_REUSEADDR解决 TIME_WAIT导致的端口占用问题，确保服务器崩溃后能快速重启
    //SO_REUSEPORT实现多进程/多线程共享同一端口，提升并发性能（如 Nginx 的 Worker 进程）。
    void ReuseAddress()
    {
        int opt = 1;
        setsockopt(_sockfd,SOL_SOCKET,SO_REUSEADDR,(void*)&opt,sizeof(opt));
        opt = 1;
        setsockopt(_sockfd,SOL_SOCKET,SO_REUSEPORT,(void*)&opt,sizeof(opt));
    }
    //设置sockfd为非阻塞
    void SetNonBlock()
    {
        int flag = fcntl(_sockfd,F_GETFL,0);
        flag |= O_NONBLOCK;
        fcntl(_sockfd,F_SETFL,flag);
    }
private:
    int _sockfd;

};
class Poller;//对poller模块进行声明
//channel模块,监控一个描述符的时间以及执行回调函数
class Channel
{
using EventCallBack = std::function<void()>;//回调函数类型
public:
    Channel(int fd,Poller* poller):_fd(fd),_events(0),_revents(0),_poller(poller){}
    //设置revents
    void SetRevents(uint32_t event)
    {
        _revents = event;
    }
    //获取文件描述符
    int GetFd(){return _fd;}
    //获取事件
    uint32_t GetEvent(){return _events;}

    //有关POller的函数，添加或删除监控事件
    //此处仅作声明，实现在Poller类后
    void Update();
    void Remove();
    
    //设置读监控
    void EnableRead(){_events |= EPOLLIN;Update();}
    //设置写监控
    void EnableWrite(){_events |= EPOLLOUT;Update();}
    //取消读监控
    void DisAbleRead(){_events &= ~EPOLLIN;Update();}
    //取消写监控
    void DisAbleWrite(){_events &= ~EPOLLOUT;Update();}
    //关闭所有监控
    void DisAbleAll(){_events = 0;Update();}
    //是否已经可读
    bool ReadAble(){return _events & EPOLLIN;}
    //是否以及可写
    bool WriteAble(){return _events & EPOLLOUT;}
    //设置回调函数
    void SetReadCallBack(const EventCallBack& cb){_read_callBack = cb;}
    void SetWriteCallBack(const EventCallBack& cb){_write_callBack = cb;}
    void SetErrorCallBack(const EventCallBack& cb){_error_callBack = cb;}
    void SetCloseCallBack(const EventCallBack& cb){_close_callBack = cb;}
    void SetEventCallBack(const EventCallBack& cb){_event_callBack = cb;}

    //执行回调函数
    void Handle(){
        if(_revents & EPOLLIN || _revents & EPOLLRDHUP || _revents & EPOLLPRI)
        {
            if(_read_callBack)
                _read_callBack();
            //任意事件的回调，针对读写事件,要在读写后执行，刷新连接的活跃度
            if(_event_callBack)
                _event_callBack();
        }
        //写事件有可能会释放连接，所以不能在写事件就绪后，再次进行别的事件处理
        //会不安全
        if(_revents & EPOLLOUT)
        {
            if(_write_callBack)
                _write_callBack();
            //任意事件的回调，针对读写事件,要在读写后执行，刷新连接的活跃度
            if(_event_callBack)
                _event_callBack();
        }
        else if(_revents & EPOLLERR)
        {
            //放在错误回调前面，错误回调可能关闭连接，一旦关闭，再去执行任意回调就没有意义
            if(_event_callBack)
                _event_callBack();
            if(_error_callBack)
            _error_callBack();
        }
        //异常关闭
        else if(_revents & EPOLLHUP)
        {
            //放在异常回调前面，异常回调可能关闭连接，一旦关闭，再去执行任意回调就没有意义
            if(_event_callBack)
                _event_callBack();
            if(_close_callBack)
                _close_callBack();
        }
        
    }
private:
    int _fd;
    uint32_t _events;//监控的事件
    uint32_t _revents;//就绪的事件
    Poller* _poller;
    //读回调，写回调，错误回调，关闭回调，任意回调
    EventCallBack _read_callBack;
    EventCallBack _write_callBack;
    EventCallBack _error_callBack;
    EventCallBack _close_callBack;
    EventCallBack _event_callBack;
};
#define MAX_SIZE 1024
//Poller模块
class Poller
{
public:
    Poller(){
        _epollfd = epoll_create1(MAX_SIZE);
        if (_epollfd == -1) {
        ERROR_LOG("epoll_create1 failed");
        exit(EXIT_FAILURE);
        }
    }
    //添加或修改事件监控
    void UpdateEvent(Channel& channel)
    {
        //不存在添加
        if(!InChannels(channel))
        {
            //先维护在hash
            _channels.insert(std::make_pair(channel.GetFd(),channel));
            Update(channel,EPOLL_CTL_ADD);
        }
        //存在修改
        else{
            Update(channel,EPOLL_CTL_MOD);
        }
    }
    //移除事件监控
    void RemoveEvent(Channel& channel)
    {
        //先判断在不在hash里
        auto it = _channels.find(channel.GetFd());
        if(it != _channels.end())
        {
            _channels.erase(it);
            Update(channel,EPOLL_CTL_DEL);
        }
        else
        {
            DEBUG_LOG("HASH IS WRONG!");
        }
    }
    //开始监控，保存活跃连接
    void Poll(std::vector<Channel*>* v)
    {
        //int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
        //事件监控
        int ret = epoll_wait(_epollfd,_evs,MAX_SIZE,-1); 
        if(ret < 0)
        {
            if(errno == EINTR)
            {
                DEBUG_LOG("EPOLL WAIT WAS BEAT!");
                return;
            }
            ERROR_LOG("epoll wait failed!");
            exit(-1);
        }
        else{
            //遍历数组 1.检查合法性 2.设置每个就绪channel的就绪事件 3.维护v
            for(int i = 0;i < ret;i++)
            {
                //既然都开始监控，那么这个channel之前一定在_channels里
                auto it = _channels.find(_evs[i].data.fd);
                assert(it != _channels.end());
                it->second.SetRevents(_evs[i].events);//设置就绪事件给就绪channel
                v->push_back(&it->second);
            }

        }
    }
private:
    //对epoll的直接操作
    void Update(Channel& channel,int op)
    {
        struct epoll_event ev;
        ev.data.fd = channel.GetFd();
        ev.events = channel.GetEvent();//把要监控的数据告诉epoll,epoll返回就绪的事件
        //int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
        if(epoll_ctl(_epollfd,op,channel.GetFd(),&ev) == -1)
            ERROR_LOG("epoll_ctlfail!");
    }
    //检查当前channel是否在哈希表里
    bool InChannels(Channel& channel)
    {
        auto it = _channels.find(channel.GetFd());
        if(it == _channels.end()) return false;
        return true;
    }
private:
    //epll句柄
    int _epollfd;
    //哈希表--<fd,channel>
    std::unordered_map<int,Channel> _channels;
    //活跃事件保存数组
    struct epoll_event _evs[MAX_SIZE];
};
//在Channel类中使用了Poller的成员，在其后声明
void Channel::Update(){return _poller->UpdateEvent(*this);}
void Channel::Remove(){return _poller->RemoveEvent(*this);}